package ch.sv7.tool.dbmanager.db.ant;

import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.StringTokenizer;

import ch.sv7.tool.dbmanager.DbManagerException;
import ch.sv7.tool.dbmanager.db.DatabaseSchema;
import ch.sv7.tool.dbmanager.db.TableSchema;
import ch.sv7.tool.dbmanager.db.dialect.Dialect;
import ch.sv7.tool.dbmanager.db.dialect.DialectFactory;
import ch.sv7.tool.dbmanager.db.sql.SQLDatabaseSchemaFactory;
import ch.sv7.tool.dbmanager.db.xml.XmlDatabaseSchemaFactory;
import ch.sv7.tool.dbmanager.types.ConnectionTypesInfo;
import ch.sv7.tool.dbmanager.types.TypesInfo;
import ch.sv7.tool.log.AntAppender;
import ch.sv7.tool.log.Appender;
import ch.sv7.tool.log.Logger;

public class TablesSqlTask extends SqlTask {

	private String schema;

	private String tables;

	private String directory;

	private String structure;
	
	private String dialect;
	private String dialectProperties;
	private String contextProperties;

	private String catalog;

	private String ignoreColumns;

	private String zip;

	private String filePattern = "TABLENAME";

	private boolean forceUpperCase = false;

	private boolean forceLowerCase = false;
	
	private String encoding = "UTF-8";

	public TablesSqlTask() {
		Logger.setAppender(new AntAppender(this, Appender.LEVEL_INFO));
	}

	public void setStructure(String structure) {
		this.structure = structure;
		
	}

	public String getEncoding() {
		return encoding;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}

	public void setSchema(String schema) {
		this.schema = schema;
	}

	public void setTables(String tables) {
		this.tables = tables;
	}

	public void setDirectory(String directory) {
		this.directory = directory;
	}

	public void setCatalog(String catalog) {
		this.catalog = catalog;
	}

	public DatabaseSchema getDatabaseSchema(Connection conn, String tables) throws DbManagerException {
		DatabaseSchema dbSchema = null;
		if (structure != null && structure.length() > 0) {
			log("DB structure extracted from file : " + structure);
			try {
				XmlDatabaseSchemaFactory xmlFactory = new XmlDatabaseSchemaFactory(structure, schema);
				dbSchema = xmlFactory.getDatabaseSchema(tables);
			} catch (FileNotFoundException e) {
				throw new DbManagerException("Unable to read schema from file " + structure);
			}
		} else {
			log("DB structure extracted from DB");
			TypesInfo ti = null;
			try {
				ti = new ConnectionTypesInfo(conn);
			} catch (SQLException e) {
				throw new DbManagerException("Unable to read types from database ", e);
			}
			Dialect dbDialect = DialectFactory.getInstance().getDialect(getDialect(), ti, getDialectProperties());
			SQLDatabaseSchemaFactory factory = new SQLDatabaseSchemaFactory(conn, catalog, schema, dbDialect);
			dbSchema = factory.getDatabaseSchema(tables);
		}
		removeIgnoreColumns(dbSchema, getIgnoreColumns());
		dbSchema = forceCase(dbSchema);
		return dbSchema;
	}

	private DatabaseSchema forceCase(DatabaseSchema schema) {
		if (forceLowerCase) {
			schema.forceLowerCase();
		} else if (forceUpperCase) {
			schema.forceUpperCase();
		}
		return schema;
	}

	private static void removeIgnoreColumns(DatabaseSchema schema, String ignoredColumns) {
		if (ignoredColumns == null || ignoredColumns.trim().length() == 0)
			return;
		StringTokenizer tokens = new StringTokenizer(ignoredColumns, ",");
		while (tokens.hasMoreTokens()) {
			String ignoredColumn = tokens.nextToken().trim();
			int p = ignoredColumn.indexOf(".");
			if (p != -1) {
				String tableName = ignoredColumn.substring(0, p);
				String column = ignoredColumn.substring(p + 1);
				TableSchema tableSchema = schema.getTableSchema(tableName);
				System.out.println("Ignoring column : " + column + " from table : " + tableName);
				tableSchema.removeColumnSchema(column);
			}
		}
	}

	public boolean isFileZipped() {
		return "true".equalsIgnoreCase(getZip()) || "1".equals(getZip()) || "yes".equalsIgnoreCase(getZip());
	}

	public String getCatalog() {
		return catalog;
	}

	public String getDirectory() {
		return directory;
	}

	public String getSchema() {
		return schema;
	}

	public String getStructure() {
		return structure;
	}

	public String getTables() {
		return tables;
	}

	public String getFilePattern() {
		return filePattern;
	}

	public void setFilePattern(String string) {
		filePattern = string;
	}

	public String getIgnoreColumns() {
		return ignoreColumns;
	}

	public void setIgnoreColumns(String string) {
		ignoreColumns = string;
	}

	public String getZip() {
		return zip;
	}

	public void setZip(String string) {
		zip = string;
	}

	public boolean isForceUpperCase() {
		return forceUpperCase;
	}

	public void setForceUpperCase(boolean forceUpperCase) {
		this.forceUpperCase = forceUpperCase;
	}

	public boolean isForceLowerCase() {
		return forceLowerCase;
	}

	public void setForceLowerCase(boolean forceLowerCase) {
		this.forceLowerCase = forceLowerCase;
	}

	/**
	 * @return the dialect
	 */
	public String getDialect() {
		return dialect;
	}

	/**
	 * @param dialect the dialect to set
	 */
	public void setDialect(String dialect) {
		this.dialect = dialect;
	}

	/**
	 * @return the dialectProperties
	 */
	public String getDialectProperties() {
		return dialectProperties;
	}

	/**
	 * @param dialectProperties the dialectProperties to set
	 */
	public void setDialectProperties(String dialectProperties) {
		this.dialectProperties = dialectProperties;
	}

	public String getContextProperties() {
		return contextProperties;
	}

	public void setContextProperties(String contextProperties) {
		this.contextProperties = contextProperties;
	}

}
